
//timescale  1ns/1ns
`include "../rtl/cmd_para.v"
module Can_BUS(
    input               iClk ,
    input               iRst_n        ,
    input               i_mpc_intr_n   ,
    input               i_miso      ,
    output reg                o_sck       ,
    output reg                o_mosi      ,
    output reg                o_ssn       ,
    output wire[3:0]                work_state ,
    output reg[7:0]                data1,
    output reg[7:0]               data2 ,
    output wire[63:0]       o_can_data ,
	input  [63:0] 		    i_can_data	,
    input               iM_S_slect  //0:接收 1：发送
);

parameter	IDLE = 4'd0;
parameter	SEND	 = 4'd1;//读字节
parameter	RECEIVE	 = 4'd2;
parameter	INIT = 4'd3;

reg[3:0]	state_n;
reg[3:0]	state_c;
wire wInit_Done;
wire wSSN_init;
wire wMOSI_init;
wire wSCK_init;
wire wSSN_receive;
wire wMOSI_receive;
wire wSCK_receive;
wire wSSN_send;
wire wMOSI_send;
wire wSCK_send;
reg  rInit_Start;
wire wsend_done;
wire wreceive_done;
reg [1:0] rvSend_Choose; //0:等待 1：发送 2：接收
wire wSend_En;
reg rMasterChoose;
reg [31:0] rvcnt_1;
reg [31:0] rvcnt_2;
wire wCom_Err1,wCom_Err2;
reg [1:0] rvSide1;
assign   work_state=state_c;
//SPI信息汇总
always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        o_sck<=1'b1;
        o_mosi<=1'b0;
        o_ssn<=1'b0;
    end
    else begin
        if(!wInit_Done)begin
           o_sck<=wSCK_init;
           o_mosi<=wMOSI_init;
           o_ssn<=wSSN_init;end
        else if(rvSend_Choose==2'd1)begin
           o_sck<=wSCK_send;
           o_mosi<=wMOSI_send;
           o_ssn<=wSSN_send;end
        else if(rvSend_Choose==2'd2)begin
           o_sck<=wSCK_receive;
           o_mosi<=wMOSI_receive;
           o_ssn<=wSSN_receive;end
        else begin
            o_sck<=1'b1;
            o_mosi<=1'b0;
            o_ssn<=1'b0;end

    end
end
//边沿处理
always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)
        rvSide1 <= 2'd0;
    else
        rvSide1<={rvSide1[0],wInit_Done};
end

//The first section: synchronous timing always module, formatted to describe the transfer of the secondary register to the live register�?
always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        state_c <= INIT;
    end
    else if(wCom_Err1 || wCom_Err2) begin
        state_c <= INIT; 
    end
    else
        state_c <= state_n;
end

//The second paragraph: The combinational logic always module describes the state transition condition judgment.
always@(*)begin
    case(state_c)
        INIT:state_n = rvSide1==1'b01 ? IDLE : state_c ;
        IDLE:state_n = rMasterChoose ? SEND : RECEIVE ;
        SEND:state_n = wsend_done ? IDLE : state_c ;
        RECEIVE:state_n = wreceive_done ? IDLE : state_c ;
        default:begin
            state_n = IDLE;
        end
    endcase
end

always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rInit_Start<=1'b0;
        rvSend_Choose<=2'd0;
        rMasterChoose<=1'b0;
        rvcnt_1<=32'd0;
        rvcnt_2<=32'd0;
    end
    else
        case(state_c)
        INIT:begin
            rvSend_Choose<=2'd0;
            rInit_Start<=1'b1;
            rvcnt_1<=32'd0;
            rvcnt_2<=32'd0;
            rMasterChoose<=iM_S_slect;
        end
        IDLE:begin
            rvSend_Choose<=2'd0;
            rInit_Start<=1'd0;
            rvcnt_1<=32'd0;
            rvcnt_2<=32'd0;
        end
        SEND:begin
            rvSend_Choose<=2'd1;
            rMasterChoose<=wsend_done ? ~rMasterChoose : rMasterChoose;
            rvcnt_1<=iM_S_slect ? rvcnt_1+32'd1 : 32'd0;
        end
        RECEIVE:begin
            rvSend_Choose<=2'd2;
            rMasterChoose<=wreceive_done ? ~rMasterChoose : rMasterChoose;
            rvcnt_2<=iM_S_slect ? rvcnt_2+32'd1 : 32'd0;
        end
        default:begin
            state_n = IDLE;
        end
    endcase

end
assign  wCom_Err1= rvcnt_1>=32'd25000000 ? 1'b1 :1'b0;
assign  wCom_Err2= rvcnt_2>=32'd25000000 ? 1'b1 :1'b0;
MCP_INIT u_MCP_INIT(
    .iClk         (iClk         ),
    .iRst_n       (iRst_n       ),
    .iInit_Start  (rInit_Start  ),
    .i_miso       (i_miso       ),
    .o_sck        (wSCK_init        ),
    .o_mosi       (wMOSI_init       ),
    .o_ssn        (wSSN_init        ),
    .oInit_Done   (wInit_Done   )
);

MCP_SEND u_MCP_SEND(
    .iClk       (iClk       ),
    .iRst_n     (iRst_n     ),
    .i_miso     (i_miso     ),
    .o_sck      (wSCK_send      ),
    .o_mosi     (wMOSI_send     ),
    .o_ssn      (wSSN_send      ),
    .iSend_Req  (wSend_En && wInit_Done ),
    .osend_done (wsend_done ),
    .i_can_data (i_can_data )
);

MCP_RECIEVE u_MCP_RECIEVE(
    .iClk          (iClk          ),
    .iRst_n        (iRst_n        ),
    .i_miso        (i_miso        ),
    .o_sck         (wSCK_receive         ),
    .o_mosi        (wMOSI_receive        ),
    .o_ssn         (wSSN_receive         ),
    .ivSend_Choose (rvSend_Choose ),
    .oSend_En      (wSend_En      ),
    .oreceive_done (wreceive_done ),
    .o_can_data    (o_can_data    )
);

endmodule



























